﻿#region Copyright
// Copyright (c) 2011-2012 RaisingForce Team (Alikin Sergey)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using RaisingForce.Raise.Language.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;

namespace RaisingForce.Raise.Tests
{


    /// <summary>
    ///Это класс теста для WordTypePoolTest, в котором должны
    ///находиться все модульные тесты WordTypePoolTest
    ///</summary>
    [TestClass()]
    public class WordTypePoolTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Получает или устанавливает контекст теста, в котором предоставляются
        ///сведения о текущем тестовом запуске и обеспечивается его функциональность.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Дополнительные атрибуты теста
        // 
        //При написании тестов можно использовать следующие дополнительные атрибуты:
        //
        //ClassInitialize используется для выполнения кода до запуска первого теста в классе
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //ClassCleanup используется для выполнения кода после завершения работы всех тестов в классе
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //TestInitialize используется для выполнения кода перед запуском каждого теста
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //TestCleanup используется для выполнения кода после завершения каждого теста
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///Тест для Конструктор WordTypePool
        ///</summary>
        [TestMethod()]
        public void WordTypePoolConstructorTest()
        {
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            Assert.AreEqual(0, target.WordTypeCount);
            registerDefaultWordTypes = true;
            target = new WordTypePool(registerDefaultWordTypes);
            Assert.AreEqual(22, target.WordTypeCount);
            Assert.IsTrue(target.ContainsName(WordTypeNames.BypassObject));
            Assert.IsTrue(target.ContainsName(WordTypeNames.ChainName));
            Assert.IsTrue(target.ContainsName(WordTypeNames.ComeFromChain));
            Assert.IsTrue(target.ContainsName(WordTypeNames.CounterBoundary));
            Assert.IsTrue(target.ContainsName(WordTypeNames.CounterIncrementing));
            Assert.IsTrue(target.ContainsName(WordTypeNames.CounterInitialized));
            Assert.IsTrue(target.ContainsName(WordTypeNames.GoToChain));
            Assert.IsTrue(target.ContainsName(WordTypeNames.IncrementAndMove));
            Assert.IsTrue(target.ContainsName(WordTypeNames.IncrementCounter));
            Assert.IsTrue(target.ContainsName(WordTypeNames.IncrementCounterTwice));
            Assert.IsTrue(target.ContainsName(WordTypeNames.InitializeCounter));
            Assert.IsTrue(target.ContainsName(WordTypeNames.LookForBorder));
            Assert.IsTrue(target.ContainsName(WordTypeNames.LookForNothing));
            Assert.IsTrue(target.ContainsName(WordTypeNames.LookForObject));
            Assert.IsTrue(target.ContainsName(WordTypeNames.Move));
            Assert.IsTrue(target.ContainsName(WordTypeNames.MoveAndGoToChain));
            Assert.IsTrue(target.ContainsName(WordTypeNames.MoveAndIncrement));
            Assert.IsTrue(target.ContainsName(WordTypeNames.MoveToObject));
            Assert.IsTrue(target.ContainsName(WordTypeNames.MoveTwice));
            Assert.IsTrue(target.ContainsName(WordTypeNames.ObjectNear));
            Assert.IsTrue(target.ContainsName(WordTypeNames.ObjectThere));
            Assert.IsTrue(target.ContainsName(WordTypeNames.SetCounter));
        }

        /// <summary>
        ///Тест для ContainsName
        ///</summary>
        [TestMethod()]
        public void ContainsNameTest()
        {
            bool registerDefaultWordTypes = true;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            string wordTypeName = WordTypeNames.ObjectNear;
            bool expected = true;
            bool actual;
            actual = target.ContainsName(wordTypeName);
            Assert.AreEqual(expected, actual);
            registerDefaultWordTypes = false;
            target = new WordTypePool(registerDefaultWordTypes);
            expected = false;
            actual = target.ContainsName(wordTypeName);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для ContainsWordType
        ///</summary>
        [TestMethod()]
        public void ContainsWordTypeTest()
        {
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            WordType wordType = null;
            bool expected = false;
            bool actual;
            actual = target.ContainsWordType(wordType);
            Assert.AreEqual(expected, actual);
            wordType = new IfWordType("Sample", typeof(ObjectGlyph));
            expected = false;
            actual = target.ContainsWordType(wordType);
            Assert.AreEqual(expected, actual);
            target.RegisterWordType(wordType);
            expected = true;
            actual = target.ContainsWordType(wordType);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для GetEnumerator
        ///</summary>
        [TestMethod()]
        public void GetEnumeratorTest()
        {
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            target.RegisterWordType(new IfWordType("Sample1", typeof(NumberGlyph)));
            target.RegisterWordType(new ThenWordType("Sample2", typeof(DirectionGlyph)));
            IEnumerator<WordType> actual;
            actual = target.GetEnumerator();
            Assert.IsNotNull(actual);
            int counter = 0;
            while (actual.MoveNext())
            {
                Assert.IsTrue(
                    actual.Current.Name == "Sample1"
                    || actual.Current.Name == "Sample2");
                counter += 1;
            }
            Assert.AreEqual(2, counter);
        }

        /// <summary>
        ///Тест для GetWordType
        ///</summary>
        [TestMethod()]
        public void GetWordTypeTest()
        {
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            string wordTypeName = "Sample";
            WordType expected = new ChainWordType(wordTypeName, typeof(ChainGlyph));
            target.RegisterWordType(expected);
            WordType actual;
            actual = target.GetWordType(wordTypeName);
            Assert.AreSame(expected, actual);
        }

        /// <summary>
        ///Тест для RegisterDefaultWordTypes
        ///</summary>
        [TestMethod()]
        public void RegisterDefaultWordTypesTest()
        {
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            bool expected = true;
            bool actual;
            actual = target.RegisterDefaultWordTypes();
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(22, target.WordTypeCount);
            expected = false;
            actual = target.RegisterDefaultWordTypes();
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(22, target.WordTypeCount);
            target.UnregisterWordType(target.GetWordType(WordTypeNames.MoveAndIncrement));
            Assert.IsFalse(target.ContainsName(WordTypeNames.MoveAndIncrement));
            Assert.AreEqual(21, target.WordTypeCount);
            expected = true;
            actual = target.RegisterDefaultWordTypes();
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(22, target.WordTypeCount);
            Assert.IsTrue(target.ContainsName(WordTypeNames.MoveAndIncrement));
            expected = false;
            actual = target.RegisterDefaultWordTypes();
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(22, target.WordTypeCount);
        }

        /// <summary>
        ///Тест для RegisterWordType
        ///</summary>
        [TestMethod()]
        public void RegisterWordTypeTest()
        {
            const string wordTypeName = "Sample";
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            WordType wordType = new IfWordType(wordTypeName, typeof(ObjectGlyph));
            Assert.IsFalse(target.ContainsWordType(wordType));
            Assert.IsFalse(target.ContainsName(wordTypeName));
            target.RegisterWordType(wordType);
            Assert.AreEqual(1, target.WordTypeCount);
            Assert.IsTrue(target.ContainsWordType(wordType));
            Assert.IsTrue(target.ContainsName(wordTypeName));
        }

        /// <summary>
        ///Тест для TryRegisterWordType
        ///</summary>
        [TestMethod()]
        public void TryRegisterWordTypeTest()
        {
            const string wordTypeName = "Sample";
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            WordType wordType = new IfWordType(wordTypeName, typeof(ObjectGlyph));
            bool expected = true;
            bool actual;
            Assert.IsFalse(target.ContainsWordType(wordType));
            Assert.IsFalse(target.ContainsName(wordTypeName));
            actual = target.TryRegisterWordType(wordType);
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(1, target.WordTypeCount);
            Assert.IsTrue(target.ContainsWordType(wordType));
            Assert.IsTrue(target.ContainsName(wordTypeName));
            expected = false;
            actual = target.TryRegisterWordType(wordType);
            Assert.AreEqual(1, target.WordTypeCount);
            Assert.IsTrue(target.ContainsWordType(wordType));
            Assert.IsTrue(target.ContainsName(wordTypeName));
        }

        /// <summary>
        ///Тест для UnregisterWordType
        ///</summary>
        [TestMethod()]
        public void UnregisterWordTypeTest()
        {
            const string wordTypeName = "Sample";
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            WordType wordType = new IfWordType(wordTypeName, typeof(ObjectGlyph));
            target.RegisterWordType(wordType);
            Assert.AreEqual(1, target.WordTypeCount);
            Assert.IsTrue(target.ContainsWordType(wordType));
            Assert.IsTrue(target.ContainsName(wordTypeName));
            target.UnregisterWordType(wordType);
            Assert.AreEqual(0, target.WordTypeCount);
            Assert.IsFalse(target.ContainsWordType(wordType));
            Assert.IsFalse(target.ContainsName(wordTypeName));
        }

        /// <summary>
        ///Тест для WordTypeCount
        ///</summary>
        [TestMethod()]
        public void WordTypeCountTest()
        {
            const string wordTypeName = "Sample";
            bool registerDefaultWordTypes = false;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            int actual;
            actual = target.WordTypeCount;
            Assert.AreEqual(0, actual);
            WordType wordType = new IfWordType(wordTypeName, typeof(ObjectGlyph));
            target.RegisterWordType(wordType);
            actual = target.WordTypeCount;
            Assert.AreEqual(1, actual);
            target.UnregisterWordType(wordType);
            actual = target.WordTypeCount;
            Assert.AreEqual(0, actual);
        }

        /// <summary>
        ///Тест для GetAllowedWordTypeNames
        ///</summary>
        [TestMethod()]
        public void GetAllowedWordTypeNamesTest()
        {
            bool registerDefaultWordTypes = true;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            IList<string> expected = new string[]
            {
                WordTypeNames.BypassObject,
                WordTypeNames.ChainName,
                WordTypeNames.ComeFromChain, 
                WordTypeNames.CounterBoundary, 
                WordTypeNames.CounterIncrementing,
                WordTypeNames.CounterInitialized,
                WordTypeNames.GoToChain, 
                WordTypeNames.IncrementAndMove, 
                WordTypeNames.IncrementCounter, 
                WordTypeNames.IncrementCounterTwice, 
                WordTypeNames.InitializeCounter,
                WordTypeNames.LookForBorder,
                WordTypeNames.LookForNothing, 
                WordTypeNames.LookForObject, 
                WordTypeNames.Move, 
                WordTypeNames.MoveAndGoToChain, 
                WordTypeNames.MoveAndIncrement,
                WordTypeNames.MoveToObject, 
                WordTypeNames.MoveTwice,
                WordTypeNames.ObjectNear, 
                WordTypeNames.ObjectThere, 
                WordTypeNames.SetCounter
            };
            IList<string> actual;
            actual = target.GetAllowedWordTypeNames();
            Assert.AreEqual(expected.Count, actual.Count);
            foreach (string expectedItem in expected)
            {
                Assert.IsTrue(actual.Contains(expectedItem));
            }
        }

        /// <summary>
        ///Тест для GetWordType
        ///</summary>
        [TestMethod()]
        public void GetWordTypeTest1()
        {
            bool registerDefaultWordTypes = true;
            WordTypePool target = new WordTypePool(registerDefaultWordTypes);
            Type primaryGlyphType = typeof(CounterGlyph);
            Type secondaryGlyphType = null;
            // IncrementCounter
            WordType expected = target.GetWordType(WordTypeNames.IncrementCounter);
            WordType actual;
            actual = target.GetWordType(primaryGlyphType, secondaryGlyphType, WordContext.Then);
            Assert.AreSame(expected, actual);
            // LookForBorder
            primaryGlyphType = typeof(DirectionGlyph);
            secondaryGlyphType = typeof(ZeroGlyph);
            expected = target.GetWordType(WordTypeNames.LookForBorder);
            actual = target.GetWordType(primaryGlyphType, secondaryGlyphType, WordContext.If);
            Assert.AreSame(expected, actual);
            // Unknown WordType
            primaryGlyphType = typeof(ChainGlyph);
            secondaryGlyphType = typeof(ChainGlyph);
            expected = null;
            actual = target.GetWordType(primaryGlyphType, secondaryGlyphType, WordContext.If);
            Assert.AreSame(expected, actual);
        }
    }
}
